bitkeeper revision 1.1159.155.6 (418960fcc8HEe_ZDfftWd3gpkqGjnw)
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Wed, 3 Nov 2004 22:51:40 +0000 (22:51 +0000)
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Wed, 3 Nov 2004 22:51:40 +0000 (22:51 +0000)
Cleanup code to reconnect domain control channel after xend restart.
Based on code by Mike Wray.

tools/python/xen/lowlevel/xu/xu.c
tools/python/xen/xend/XendConsole.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/server/SrvDaemon.py
tools/python/xen/xend/server/channel.py
tools/python/xen/xend/server/console.py
tools/python/xen/xend/server/controller.py

index 29213e93ff21280d67e4ef33b76a3f8434f56fa1..9a676936830e4057d90fc14d4168d4f2a18e380f 100644 (file)
@@ -1054,13 +1054,16 @@ static PyMethodDef xu_port_methods[] = {
 
 staticforward PyTypeObject xu_port_type;
 
-static PyObject *xu_port_new(PyObject *self, PyObject *args)
+static PyObject *xu_port_new(PyObject *self, PyObject *args, PyObject *kwds)
 {
     xu_port_object *xup;
     u32 dom;
     int port1 = 0, port2 = 0;
 
-    if ( !PyArg_ParseTuple(args, "i|ii", &dom, &port1, &port2) )
+    static char *kwd_list[] = { "dom", "local_port", "remote_port", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
+                                      &dom, &port1, &port2) )
         return NULL;
 
     xup = PyObject_New(xu_port_object, &xu_port_type);
@@ -1435,7 +1438,7 @@ static PyMethodDef xu_methods[] = {
       "Create a new notifier." },
     { "message", xu_message_new, METH_VARARGS, 
       "Create a new communications message." },
-    { "port", xu_port_new, METH_VARARGS, 
+    { "port", (PyCFunction)xu_port_new, METH_VARARGS | METH_KEYWORDS, 
       "Create a new communications port." },
     { "buffer", xu_buffer_new, METH_VARARGS, 
       "Create a new ring buffer." },
index ea79645be91bf4d9ea1ceebbf05a317ab694af29..6825dc5baab73269f23e19649c468022c63ca7d8 100644 (file)
@@ -32,9 +32,8 @@ class XendConsole:
     def consoles(self):
         return daemon.get_consoles()
     
-    def console_create(self, dom, console_port=None, remote_port=0):
-        consinfo = daemon.console_create(dom, console_port=console_port,
-                                         remote_port=remote_port)
+    def console_create(self, dom, console_port=None):
+        consinfo = daemon.console_create(dom, console_port=console_port)
         return consinfo
     
     def console_get(self, id):
index 36d6a333615f53fbd5365b280d40943a8c3925e1..70cd68db1cc08e9e0f273f66e3db0226799d4249 100644 (file)
@@ -753,17 +753,34 @@ class XendDomainInfo:
         @param ramdisk: kernel ramdisk
         @param cmdline: kernel commandline
         """
-        #self.init_domain()
+
+        self.create_channel()
         if self.console:
             self.console.registerChannel()
         else:
             self.console = xendConsole.console_create(
-                self.dom, console_port=self.console_port, remote_port=1)
+                self.dom, console_port=self.console_port)
         self.build_domain(ostype, kernel, ramdisk, cmdline)
         self.image = kernel
         self.ramdisk = ramdisk
         self.cmdline = cmdline
 
+    def create_channel(self):
+        """Create the channel to the domain.
+        If saved info is available recreate the channel using the saved ports.
+
+        @return: channel
+        """
+        local = 0
+        remote = 1
+        if self.savedinfo:
+            consinfo = sxp.child(self.savedinfo, "console")
+            if consinfo:
+                local = int(sxp.child_value(consinfo, "local_port", 0))
+                remote = int(sxp.child_value(consinfo, "remote_port", 1))
+        return xend.createDomChannel(self.dom, local_port=local,
+                                     remote_port=remote)
+
     def create_devices(self):
         """Create the devices for a vm.
 
index cc7da8ee439d0f6d64b630df7f7e0aaee2cf6bca..41a5965221734f811f373c52825446a40eb7e559 100644 (file)
@@ -638,12 +638,22 @@ class Daemon:
     def getDomChannel(self, dom):
         """Get the channel to a domain.
 
-        dom domain
-
-        returns channel (or None)
+        @param dom: domain
+        @return: channel (or None)
         """
         return self.channelF.getDomChannel(dom)
 
+    def createDomChannel(self, dom, local_port=0, remote_port=0):
+        """Get the channel to a domain, creating if necessary.
+
+        @param dom: domain
+        @param local_port: optional local port to re-use
+        @param remote_port: optional remote port to re-use
+        @return: channel
+        """
+        return self.channelF.domChannel(dom, local_port=local_port,
+                                        remote_port=remote_port)
+
     def blkif_create(self, dom, recreate=0):
         """Create or get a block device interface controller.
         
@@ -671,13 +681,12 @@ class Daemon:
     def netif_get(self, dom):
         return self.netifCF.getControllerByDom(dom)
 
-    def console_create(self, dom, console_port=None, remote_port=0):
+    def console_create(self, dom, console_port=None):
         """Create a console for a domain.
         """
         console = self.consoleCF.getControllerByDom(dom)
         if console is None:
-            console = self.consoleCF.createController(dom, console_port,
-                                                      remote_port=remote_port)
+            console = self.consoleCF.createController(dom, console_port)
         return console
 
     def consoles(self):
index 1401c35435cec10ac376bc5cfa59b9b17f119763..127f38f2c0b615a035f39d825320e4c1965e34e3 100755 (executable)
@@ -45,7 +45,7 @@ class ChannelFactory:
             del self.channels[idx]
             self.notifier.unbind(idx)
 
-    def domChannel(self, dom, remote_port=0):
+    def domChannel(self, dom, local_port=0, remote_port=0):
         """Get the channel for the given domain.
         Construct if necessary.
 
@@ -55,7 +55,8 @@ class ChannelFactory:
         """
         chan = self.getDomChannel(dom)
         if not chan:
-            chan = Channel(self, dom, remote_port=remote_port)
+            chan = Channel(self, dom, local_port=local_port,
+                           remote_port=remote_port)
             self.addChannel(chan)
         return chan
 
@@ -91,10 +92,25 @@ class ChannelFactory:
         """
         self.delChannel(channel.idx)
 
-    def createPort(self, dom, remote_port=0):
+    def createPort(self, dom, local_port=0, remote_port=0):
         """Create a port for a channel to the given domain.
+        If only the domain is specified, a new channel with new port ids is
+        created.  If one port id is specified and the given port id is in use,
+        the other port id is filled.  If one port id is specified and the
+        given port id is not in use, a new channel is created with one port
+        id equal to the given id and a new id for the other end.  If both
+        port ids are specified, a port is reconnected using the given port
+        ids.
+
+        @param dom: domain
+        @param local: local port id to use
+        @type  local: int
+        @param remote: remote port id to use
+        @type  remote: int
+        @return: port object
         """
-        return xu.port(dom, 0, remote_port)
+        return xu.port(dom, local_port=int(local_port),
+                       remote_port=int(remote_port))
 
 def channelFactory():
     """Singleton constructor for the channel factory.
@@ -200,7 +216,7 @@ class Channel(BaseChannel):
     are multiplexed over the channel (console, block devs, net devs).
     """
 
-    def __init__(self, factory, dom, remote_port=0):
+    def __init__(self, factory, dom, local_port=0, remote_port=0):
         """Create a channel to the given domain using the given factory.
 
         Do not call directly, use domChannel on the factory.
@@ -209,7 +225,8 @@ class Channel(BaseChannel):
         # Domain.
         self.dom = int(dom)
         # Domain port (object).
-        self.port = self.factory.createPort(dom, remote_port=remote_port)
+        self.port = self.factory.createPort(dom, local_port=local_port,
+                                            remote_port=remote_port)
         # Channel port (int).
         self.idx = self.port.local_port
         # Registered devices.
index 3d302dbe3f93544f5fc3144942e1fb2881ab03d1..ea4bf499215d658a52d88779f37268ceea8ed789 100755 (executable)
@@ -48,7 +48,6 @@ class ConsoleProtocol(protocol.Protocol):
             self.loseConnection()
 
     def write(self, data):
-        #if not self.connected: return -1
         self.transport.write(data)
         return len(data)
 
@@ -81,14 +80,13 @@ class ConsoleControllerFactory(controller.ControllerFactory):
     """Factory for creating console controllers.
     """
 
-    def createController(self, dom, console_port=None, remote_port=0):
+    def createController(self, dom, console_port=None):
         if console_port is None:
             console_port = CONSOLE_PORT_BASE + dom
         for c in self.getControllers():
             if c.console_port == console_port:
                 raise XendError('console port in use: ' + str(console_port))
-        console = ConsoleController(self, dom, console_port,
-                                    remote_port=remote_port)
+        console = ConsoleController(self, dom, console_port)
         self.addController(console)
         log.info("Created console id=%s domain=%d port=%d",
                  console.idx, console.dom, console.console_port)
@@ -112,9 +110,8 @@ class ConsoleController(controller.Controller):
     STATUS_CONNECTED = 'connected'
     STATUS_LISTENING = 'listening'
 
-    def __init__(self, factory, dom, console_port, remote_port=0):
-        controller.Controller.__init__(self, factory, dom,
-                                       remote_port=remote_port)
+    def __init__(self, factory, dom, console_port):
+        controller.Controller.__init__(self, factory, dom)
         self.addMethod(CMSG_CONSOLE, 0, None)
         self.status = self.STATUS_NEW
         self.addr = None
index 5b2d7e25a02fc1317854e010ab837c4edb067f6b..c8962d467592919c83cd61147440851826a47484 100755 (executable)
@@ -68,7 +68,7 @@ class CtrlMsgRcvr:
     @type responders: {int:Responder}
     """
 
-    def __init__(self, remote_port=0):
+    def __init__(self):
         self.channelFactory = channel.channelFactory()
         self.majorTypes = {}
         self.dom = None
@@ -76,7 +76,6 @@ class CtrlMsgRcvr:
         self.idx = None
         self.responders = {}
         self.timeout = 10
-        self.remote_port = remote_port
 
     def setTimeout(self, timeout):
         self.timeout = timeout
@@ -218,8 +217,7 @@ class CtrlMsgRcvr:
         channel to our domain. Once we have registered, the channel
         will call requestReceived or responseReceived for our messages.
         """
-        self.channel = self.channelFactory.domChannel(self.dom,
-                                                      self.remote_port)
+        self.channel = self.channelFactory.domChannel(self.dom)
         self.idx = self.channel.getIndex()
         if self.majorTypes:
             self.channel.registerDevice(self.getMajorTypes(), self)
@@ -364,8 +362,8 @@ class Controller(CtrlMsgRcvr):
     @type idx:     String
     """
 
-    def __init__(self, factory, dom, remote_port=0):
-        CtrlMsgRcvr.__init__(self, remote_port=remote_port)
+    def __init__(self, factory, dom):
+        CtrlMsgRcvr.__init__(self)
         self.factory = factory
         self.dom = int(dom)
         self.channel = None